﻿using Foundation.Service.Bus.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Runtime.ExceptionServices;

namespace Dyao.Book.BusApplication
{
    public static class MessageHandleContextExtensions
    {
        /// <summary>
        /// 记录mq消息执行时间及扩展信息
        /// </summary>
        /// <typeparam name="T">message type</typeparam>
        /// <param name="handleContext">handle context</param>
        /// <param name="source">日志源</param>
        /// <param name="title">日志标题</param>
        /// <param name="action">业务操作</param>
        /// <param name="isThrowException">出错时是否抛出错误</param>
        /// <param name="isStartRuning">是否记录开始运行日志</param>
        /// <returns></returns>
        public static async Task LoggingAsync<T>(this MessageHandleContext<T> handleContext, string source, string title, Func<Task> action, bool isThrowException = false, bool isStartRuning = false)
             where T : IMessage
        {
            var start = DateTime.Now;
            Func<TimeSpan> getTimes = () => DateTime.Now - start;

            var logger = handleContext.ServiceProvider.GetRequiredService<ILoggerFactory>().CreateLogger(source);

            var state = handleContext.CreateScopeState();
            using (logger.BeginScope(state))
            {
                try
                {
                    if (isStartRuning)
                    {
                        logger.LogInformation($"{title}:开始[{DateTime.Now}]");
                    }
                    await action();

                    logger.LogInformation($"{title}:结束[{DateTime.Now}],耗时:[{getTimes().TotalMilliseconds}ms]");
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, $"{title},执行出错:{ex.Message},耗时:[{getTimes().TotalMilliseconds}ms]");

                    if (isThrowException)
                    {
                        //throw;
                        ExceptionDispatchInfo.Capture(ex).Throw();
                    }
                }
            }
        }

        /// <summary>
        /// 创建日志Scope Sate 字典
        /// </summary>
        /// <typeparam name="T">message type</typeparam>
        /// <param name="handleContext">handle context</param>
        /// <returns></returns>
        public static IDictionary<string, object> CreateScopeState<T>(this MessageHandleContext<T> handleContext)
             where T : IMessage
        {
            var dict = new Dictionary<string, object>();

            dict["messageType"] = handleContext.Message.GetType().Name;

            var user = handleContext.Message.User;
            if (!string.IsNullOrWhiteSpace(user?.Id))
            {
                dict["user.id"] = user.Id;
                dict["user.name"] = user.UserName;
            }

            //if (handleContext.Message is IMC.Common.Contract.TimingSchedulerCenterTaskEvent timingEvent)
            //{
            //    dict["TaskName"] = timingEvent.TaskName;

            //    if (timingEvent.MergedJobDataMap?.Any() == true)
            //    {
            //        //dict["DataMap"] = Newtonsoft.Json.JsonConvert.SerializeObject(timingEvent.MergedJobDataMap);

            //        foreach (var item in timingEvent.MergedJobDataMap)
            //        {
            //            dict["dataMap." + item.Key] = item.Value?.ToString();
            //        }
            //    }
            //}

            return dict;
        }


        /// <summary>
        /// 获取取消令牌
        /// </summary>
        /// <param name="_"></param>
        /// <returns></returns>
        public static CancellationToken GetCancellationToken(this MessageHandleContext _)
        {
            return default;
        }
    }
}
